import 'package:casdon/modules/recipe/data/model/recipe_today_model.dart';
import 'package:casdon/modules/recipe/domain/states/recipe_today_list_state.dart';
import 'package:casdon/modules/recipe/providers/recipe_provider.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

class RecipeTodayListNotifier extends AsyncNotifier<RecipeTodayListState> {
  final int pageSize = 10;
  bool _isRefreshing = false;

  @override
  Future<RecipeTodayListState> build() async {
    return fetchFirstPage();
  }

  Future<void> refresh() async {
    if (_isRefreshing) return;
    _isRefreshing = true;
    final previous = state.valueOrNull;

    try {
      final newState = await fetchFirstPage(
        sortType: state.value?.currentSort,
      );
      state = AsyncValue.data(newState);
    } catch (e, st) {
      if (previous != null) {
        state = AsyncValue.data(previous);
      } else {
        state = AsyncValue.data(RecipeTodayListState.initial());
      }
    } finally {
      _isRefreshing = false;
    }
  }

  Future<void> loadMore() async {
    final current = state.valueOrNull;
    if (current == null) return;
    final target =
        current.activeSort == TodayRecipeSortType.createTime
            ? current.dataHot
            : current.dataNew;

    if (target.isLoadingMore || !target.hasMore) return;

    final updatedTarget = target.copyWith(isLoadingMore: true);
    state = AsyncValue.data(
      current.currentSort == TodayRecipeSortType.createTime
          ? current.copyWith(dataHot: updatedTarget)
          : current.copyWith(dataNew: updatedTarget),
    );
    final nextPage = target.page + 1;

    try {
      final ret = await ref
          .read(recipeTodayListUsecaseProvider)
          .execute(
            pageNum: nextPage,
            pageSize: pageSize,
            sortType: target.sortType,
          );

      final nextItems = RecipeTodayModel.listFromApi(ret.rows);
      final updatedData = [...target.data, ...nextItems];

      final newTargetState = target.copyWith(
        data: updatedData,
        page: nextPage,
        totalSize: ret.total,
        pageSize: pageSize,
        isLoadingMore: false,
        hasMore: ret.total > updatedData.length,
      );

      state = AsyncValue.data(
        current.activeSort == TodayRecipeSortType.createTime
            ? current.copyWith(dataHot: newTargetState)
            : current.copyWith(dataNew: newTargetState),
      );
    } catch (_) {
      final resetTarget = target.copyWith(isLoadingMore: false);
      state = AsyncValue.data(
        current.activeSort == TodayRecipeSortType.createTime
            ? current.copyWith(dataHot: resetTarget)
            : current.copyWith(dataNew: resetTarget),
      );
    }
  }

  Future<RecipeTodayListState> fetchFirstPage({
    TodayRecipeSortType? sortType = TodayRecipeSortType.view,
  }) async {
    final previous = state.valueOrNull;
    sortType ??= previous?.activeSort ?? TodayRecipeSortType.view;
    const firstPage = 1;

    // 先用旧数据设置当前排序，并标记为正在刷新
    final base = previous ?? RecipeTodayListState.initial();
    final currentTarget = sortType == TodayRecipeSortType.createTime
        ? base.dataHot
        : base.dataNew;
    final refreshingTarget = currentTarget.copyWith(isLoadingMore: true);
    final optimisticState = sortType == TodayRecipeSortType.createTime
        ? base.copyWith(
            dataHot: refreshingTarget,
            currentSort: TodayRecipeSortType.createTime,
          )
        : base.copyWith(
            dataNew: refreshingTarget,
            currentSort: TodayRecipeSortType.view,
          );
    state = AsyncData(optimisticState);

    try {
      final ret = await ref
          .read(recipeTodayListUsecaseProvider)
          .execute(pageNum: firstPage, pageSize: pageSize, sortType: sortType);

      final newTypeState = RecipeTodayListTypeState(
        data: RecipeTodayModel.listFromApi(ret.rows),
        page: firstPage,
        totalSize: ret.total,
        pageSize: pageSize,
        isLoadingMore: false,
        hasMore: ret.total > ret.rows.length,
        sortType: sortType,
      );

      final nextState = (sortType == TodayRecipeSortType.createTime)
          ? (previous ?? RecipeTodayListState.initial())
              .copyWith(
                dataHot: newTypeState,
                currentSort: TodayRecipeSortType.createTime,
              )
          : (previous ?? RecipeTodayListState.initial()).copyWith(
                dataNew: newTypeState,
                currentSort: TodayRecipeSortType.view,
              );

      state = AsyncData(nextState);
      return nextState;
    } catch (_) {
      final fallbackBase = previous ?? RecipeTodayListState.initial();
      final fallbackTarget = sortType == TodayRecipeSortType.createTime
          ? fallbackBase.dataHot
          : fallbackBase.dataNew;
      final fallbackUpdated = fallbackTarget.copyWith(isLoadingMore: false);
      final merged = sortType == TodayRecipeSortType.createTime
          ? fallbackBase.copyWith(
              dataHot: fallbackUpdated,
              currentSort: TodayRecipeSortType.createTime,
            )
          : fallbackBase.copyWith(
              dataNew: fallbackUpdated,
              currentSort: TodayRecipeSortType.view,
            );
      state = AsyncData(merged);
      return merged;
    }
  }
}
